using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Options;
using RAGApp.Api.Configurations;
using RAGApp.Api.Services.Interfaces;
using System.Text.Json.Serialization;

namespace RAGApp.Api.Services;

public class XunfeiEmbeddingService : IEmbeddingService
{
    private readonly XunfeiConfig _config;
    private readonly IHttpClientFactory _httpClientFactory;
    private readonly ILogger<XunfeiEmbeddingService> _logger;

    public XunfeiEmbeddingService(
        IOptions<XunfeiConfig> config,
        IHttpClientFactory httpClientFactory,
        ILogger<XunfeiEmbeddingService> logger)
    {
        _config = config.Value;
        _httpClientFactory = httpClientFactory;
        _logger = logger;

        // 记录配置值
        _logger.LogInformation($"配置信息:");
        _logger.LogInformation($"AppId: {_config.AppId}");
        _logger.LogInformation($"ApiKey: {_config.ApiKey}");
        _logger.LogInformation($"EmbeddingDomain: {_config.EmbeddingDomain}");
        _logger.LogInformation($"EmbeddingPath: {_config.EmbeddingPath}");
    }

    public async Task<float[]> GenerateEmbeddingAsync(string text, bool isQuery = false)
    {
        var texts = new List<string> { text };
        var embeddings = await GenerateEmbeddingsAsync(texts, isQuery);
        return embeddings.FirstOrDefault() ?? Array.Empty<float>();
    }

    public async Task<List<float[]>> GenerateEmbeddingsAsync(List<string> texts, bool isQuery = false)
    {
        try
        {
            var client = _httpClientFactory.CreateClient();
            
            var date = DateTime.UtcNow.ToString("r");
            var host = _config.EmbeddingDomain.Replace("https://", "").Replace("http://", "").Trim();
            var path = _config.EmbeddingPath;

            _logger.LogInformation($"准备发送请求:");
            _logger.LogInformation($"Host: {host}");
            _logger.LogInformation($"Path: {path}");
            _logger.LogInformation($"Date: {date}");

            // 构造消息格式
            var messages = new { messages = texts.Select(t => new { content = t, role = "user" }).ToList() };
            var messagesJson = JsonSerializer.Serialize(messages);
            var messagesBase64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(messagesJson));

            var requestBody = new
            {
                header = new
                {
                    app_id = _config.AppId,
                    uid = "39769795890",
                    status = 3
                },
                parameter = new
                {
                    emb = new
                    {
                        domain = isQuery ? "query" : "para",
                        feature = new
                        {
                            encoding = "utf8"
                        }
                    }
                },
                payload = new
                {
                    messages = new
                    {
                        text = messagesBase64
                    }
                }
            };

            var jsonBody = JsonSerializer.Serialize(requestBody, new JsonSerializerOptions 
            { 
                WriteIndented = false,
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            });
            _logger.LogInformation($"请求体: {jsonBody}");

            // 构建签名字符串
            var requestLine = $"POST {path} HTTP/1.1";
            var stringToSign = string.Format("host: {0}\ndate: {1}\n{2}", host, date, requestLine);
            _logger.LogInformation($"待签名字符串:\n{stringToSign}");

            // 计算签名
            var apiSecret = _config.ApiSecret;
            _logger.LogInformation($"原始 ApiSecret: {apiSecret}");
            
            using var hmac = new HMACSHA256(Encoding.UTF8.GetBytes(apiSecret));
            var signatureBytes = hmac.ComputeHash(Encoding.UTF8.GetBytes(stringToSign));
            var signature = Convert.ToBase64String(signatureBytes);
            _logger.LogInformation($"Signature: {signature}");

            // 构造 authorization
            var authorizationOrigin = string.Format(
                "api_key=\"{0}\", algorithm=\"{1}\", headers=\"{2}\", signature=\"{3}\"",
                _config.ApiKey,
                "hmac-sha256",
                "host date request-line",
                signature);
            _logger.LogInformation($"Authorization Origin: {authorizationOrigin}");

            var authorization = Convert.ToBase64String(Encoding.UTF8.GetBytes(authorizationOrigin));
            _logger.LogInformation($"Authorization Base64: {authorization}");

            // 构造完整的 URL
            var queryParams = new Dictionary<string, string>
            {
                { "host", host },
                { "date", date },
                { "authorization", authorization }
            };
            var queryString = string.Join("&", queryParams.Select(kv => $"{kv.Key}={Uri.EscapeDataString(kv.Value)}"));
            var fullUrl = $"https://{host}{path}?{queryString}";
            _logger.LogInformation($"完整 URL: {fullUrl}");

            var request = new HttpRequestMessage(HttpMethod.Post, fullUrl);
            request.Content = new StringContent(jsonBody, Encoding.UTF8, "application/json");

            _logger.LogInformation("完整请求头:");
            foreach (var header in request.Headers)
            {
                _logger.LogInformation($"{header.Key}: {string.Join(", ", header.Value)}");
            }

            var response = await client.SendAsync(request);
            var responseContent = await response.Content.ReadAsStringAsync();
            _logger.LogInformation($"API响应: {responseContent}");
            
            response.EnsureSuccessStatusCode();

            var options = new JsonSerializerOptions
            {
                PropertyNameCaseInsensitive = true
            };

            var responseObj = JsonSerializer.Deserialize<XunfeiEmbeddingResponse>(responseContent, options);

            if (responseObj == null)
            {
                _logger.LogError("API响应反序列化失败");
                throw new Exception("API响应反序列化失败");
            }

            _logger.LogInformation($"响应头: Code={responseObj.Header?.Code}, Message={responseObj.Header?.Message}, Sid={responseObj.Header?.Sid}");

            if (responseObj.Header?.Code != 0)
            {
                _logger.LogError($"API返回错误代码: {responseObj.Header?.Code}, 错误信息: {responseObj.Header?.Message}");
                throw new Exception($"讯飞API返回错误：{responseObj.Header?.Message}");
            }

            if (responseObj.Payload?.Feature?.Text == null)
            {
                _logger.LogError("API返回的向量数据为空");
                throw new Exception("API返回的向量数据为空");
            }

            _logger.LogInformation($"向量数据状态: Status={responseObj.Payload.Feature.Status}, Encoding={responseObj.Payload.Feature.Encoding}, Seq={responseObj.Payload.Feature.Seq}");

            // 分析向量数据
            var base64Data = responseObj.Payload.Feature.Text;
            _logger.LogInformation($"Base64数据长度: {base64Data.Length}");
            
            try
            {
                var vectorBytes = Convert.FromBase64String(base64Data);
                _logger.LogInformation($"解码后的字节数组长度: {vectorBytes.Length}");
                
                if (vectorBytes.Length % 4 != 0)
                {
                    _logger.LogError($"向量数据长度不是4的倍数: {vectorBytes.Length}");
                    throw new Exception("向量数据格式错误");
                }

                var floatCount = vectorBytes.Length / 4;
                _logger.LogInformation($"预期的向量维度: {floatCount}");

                var result = new float[floatCount];
                Buffer.BlockCopy(vectorBytes, 0, result, 0, vectorBytes.Length);

                // 检查向量数据是否合理
                _logger.LogInformation($"向量的前5个值: {string.Join(", ", result.Take(5))}");
                _logger.LogInformation($"向量的最后5个值: {string.Join(", ", result.Skip(result.Length - 5))}");

                if (result.Any(float.IsNaN))
                {
                    _logger.LogError("向量中包含 NaN 值");
                    throw new Exception("向量数据包含无效值");
                }

                if (result.Any(float.IsInfinity))
                {
                    _logger.LogError("向量中包含无穷大值");
                    throw new Exception("向量数据包含无效值");
                }

                _logger.LogInformation($"成功生成向量，维度: {floatCount}");
                return new List<float[]> { result };
            }
            catch (FormatException ex)
            {
                _logger.LogError(ex, "Base64解码失败");
                throw new Exception("向量数据Base64解码失败", ex);
            }
        }
        catch (JsonException ex)
        {
            _logger.LogError(ex, "解析API响应时发生错误");
            throw new Exception("解析API响应时发生错误", ex);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "生成向量时发生错误");
            throw;
        }
    }
}

public class XunfeiEmbeddingResponse
{
    [JsonPropertyName("header")]
    public ResponseHeader? Header { get; set; }

    [JsonPropertyName("payload")]
    public EmbeddingPayload? Payload { get; set; }

    public class ResponseHeader
    {
        [JsonPropertyName("code")]
        public int Code { get; set; }

        [JsonPropertyName("message")]
        public string? Message { get; set; }

        [JsonPropertyName("sid")]
        public string? Sid { get; set; }
    }

    public class EmbeddingPayload
    {
        [JsonPropertyName("feature")]
        public EmbeddingFeature? Feature { get; set; }
    }

    public class EmbeddingFeature
    {
        [JsonPropertyName("text")]
        public string? Text { get; set; }

        [JsonPropertyName("encoding")]
        public string? Encoding { get; set; }

        [JsonPropertyName("seq")]
        public string? Seq { get; set; }

        [JsonPropertyName("status")]
        public string? Status { get; set; }
    }
} 